﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

namespace WebkitIISHost.ReadCard
{
    public class sd_Analysis
    {

        public static string database; // 数据库ip地址
        public static string username; // 数据库用户名
        public static string password; // 数据库用户密码
        public static IntPtr threadHandle; // threadFunc线程句柄

        public static List<DrillDepthInfo> drillDepthInfoList = new List<DrillDepthInfo>(); // 钻孔测深二级目录内容
        public static List<DrillAngleInfo> drillAngleInfoList = new List<DrillAngleInfo>(); // 钻孔角度二级目录
        public static List<DrillData> DrillDataList = new List<DrillData>(); // 深度角度组合后的列表
        public static List<DrillOrbitInfo> drillOrbitInfoList = new List<DrillOrbitInfo>(); // 钻孔轨迹二级目录列表

        // 读取sd卡数据: 一次读取半个扇区256字节
        private static int FILE_BEGIN = 0;
        private static int FILE_CURRENT = 1;
        private static int FILE_END = 2;

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode,
            IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);


        // 执行SQL语句，Insert Update _variant_t
        public static int executeSQL(string bstrSQL)
        {
            return 0;
        }

        // 关闭数据库连接
        public static void exitConnect()
        {
            //pConnection.Close();
            //// 释放环境
            //CoUninitialize();
        }

        public static string DriverName;
        public static SDUtils SDUtils;
        public static string IsDataToText;

        #region Create SQL

        private static int BCDToInt(byte bcd) //BCD转十进制
        {
            return (0xff & (bcd >> 4))*10 + (0xf & bcd);
        }

        public static string BCDToString(byte[] time) //BCD转十进制
        {
            string str_temp =
                string.Format("{0:D4}-{1:D2}-{2:D2} {3:D2}:{4:D2}:{5:D2}", BCDToInt(time[0]) + 2000,
                    BCDToInt(time[1]), BCDToInt(time[2]), BCDToInt(time[3]), BCDToInt(time[4]), BCDToInt(time[5]));
            return str_temp;
        }


        internal static void CreateSQL_Depth_Angle(List<DrillDepthRealData> depths)
        {
            if (IsDataToText == "1")
            {
                var groups = depths.GroupBy(o => o.DrillIndex);
                foreach (var @group in groups)
                {
                    SystemConfig.WriteLine("深度",@group.Key,@group.Select(o=>o.ToString()).ToList());
                }
            }
            else
            {
                foreach (var drillDepthRealData in depths)
                {
                    string str_SQL = "", str_temp = "";
                    str_SQL = "INSERT INTO ";
                    str_SQL += drillDepthRealData.TableName;
                    str_SQL += "([DrillHoleId], [Date], [Depth], [Displacement], [ForewardPressure], [ReversalPressure], [ForwardPressure], [BackPressure], [ChuckPressure], [holderPressure]) ";
                    str_SQL += "VALUES('";
                    str_SQL += drillDepthRealData.DrillIndex;
                    str_SQL += "',";
                    str_temp = BCDToString(drillDepthRealData.time);

                    str_SQL += "'";
                    str_SQL += str_temp;
                    str_SQL += "',";
                    str_SQL += string.Format("{0:f2}", drillDepthRealData.currDepth) + ",";
                    str_SQL += string.Format("{0:f1}", drillDepthRealData.sensorData) + ",";
                    str_SQL += string.Format("{0:f1}", drillDepthRealData.forewardPressure) + ",";
                    str_SQL += string.Format("{0:f1}", drillDepthRealData.reversalPressure) + ",";
                    str_SQL += string.Format("{0:f1}", drillDepthRealData.ForwardPressure) + ",";
                    str_SQL += string.Format("{0:f1}", drillDepthRealData.backPressure) + ",";
                    str_SQL += string.Format("{0:f1}", drillDepthRealData.chuckPressure) + ",";

                    str_SQL += string.Format("{0:f1}", drillDepthRealData.holderPressure) + ",";
                    //                str_SQL += string.Format("{0:f1}", myDrillAngleRealData.inclination) + ",";
                    //                str_SQL += string.Format("{0:f1}", myDrillAngleRealData.azimuth) + ",";
                    //                str_SQL += string.Format("{0:f1}", myDrillAngleRealData.rotation) + ",";
                    //
                    //                str_SQL += string.Format("{0:f1}", currXAxis) + ",";
                    //                str_SQL += string.Format("{0:f1}", currYAxis) + ",";
                    //                str_SQL += string.Format("{0:f1}", currZAxis) + ")";

                    sd_Analysis.executeSQL(str_SQL.ToString()).ToString();
                }
            }
        }

        internal static void CreateSQL_Angle(List<DrillAngleRealData> angles)
        {
            if (IsDataToText == "1")
            {
                var groups = angles.GroupBy(o => o.DrillIndex);
                foreach (var @group in groups)
                {
                    SystemConfig.WriteLine("角度", @group.Key, @group.Select(o => o.ToString()).ToList());
                }
            }
            else
            {
                foreach (var angle in angles)
                {
                    string str_SQL = "", str_temp = "";
                    str_SQL = string.Format("  INSERT INTO ", angle.DrillIndex);
                    str_SQL += angle.TableName;
                    str_SQL += "(OriginalId,[DrillHoleId], [Date], [Depth], [Displacement], [ForewardPressure], [ReversalPressure], [ForwardPressure], [BackPressure], [ChuckPressure], [holderPressure],[Inclination], [Azimuth], [Rotation], [XAxis], [YAxis], [ZAxis],State) ";
                    str_SQL += "VALUES('";
                    str_SQL += angle.DrillIndex;
                    str_SQL += "','";
                    str_SQL += angle.DrillIndex;
                    str_SQL += "',";
                    str_temp = BCDToString(angle.time);
                    str_SQL += "'";
                    str_SQL += str_temp;
                    str_SQL += "',";
                    str_SQL += string.Format("{0:f2}", angle.currDepth) + ",";
                    str_SQL += string.Format("{0:f1}", 0 // myDrillDepthRealData.sensorData
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", 0 //myDrillDepthRealData.forewardPressure
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", 0 // myDrillDepthRealData.reversalPressure
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", 0 // myDrillDepthRealData.ForwardPressure
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", 0 // myDrillDepthRealData.backPressure
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", 0 //myDrillDepthRealData.chuckPressure
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", 0 // myDrillDepthRealData.holderPressure
                        ) + ",";
                    str_SQL += string.Format("{0:f1}", angle.inclination) + ",";
                    str_SQL += string.Format("{0:f1}", angle.azimuth) + ",";
                    str_SQL += string.Format("{0:f1}", angle.rotation) + ",";

                    str_SQL += string.Format("{0:f1}", angle.XAxis) + ",";
                    str_SQL += string.Format("{0:f1}", angle.YAxis) + ",";
                    str_SQL += string.Format("{0:f1}", angle.ZAxis) + ",0)";

                     sd_Analysis.executeSQL(str_SQL.ToString()).ToString();
                }
            }
        }




        public static string CreateSQL_Orbit(string str_tableName, string str_drill_index, DrillOrbitRealData myDrillOrbitRealData, float currXAxis, float currYAxis, float currZAxis)
        {
            if (IsDataToText == "1")
            {
//                SystemConfig.WriteLine("轨迹",str_drill_index,
//                    string.Format("{0}^{1}^{2}^{3}^{4}^{5}^{6}^{7}^{8}", str_drill_index, BCDToString(myDrillOrbitRealData.time),
//                        myDrillOrbitRealData.cur_depth, myDrillOrbitRealData.inclination,
//                        myDrillOrbitRealData.azimuth, myDrillOrbitRealData.rotation, currXAxis, currYAxis, currZAxis));
                return "";
            }
            else
            {
                string str_SQL = "", str_temp = "";
                str_SQL = "INSERT INTO ";
                str_SQL += str_tableName;
                str_SQL += "([DrillHoleId], [Date], [Depth],[Inclination], [Azimuth], [Rotation], [XAxis], [YAxis], [ZAxis]) ";
                str_SQL += "VALUES('";
                str_SQL += str_drill_index + "',";
                str_temp = BCDToString(myDrillOrbitRealData.time);
                str_SQL += "'" + str_temp + "',";
                str_SQL += string.Format("{0:f2}", myDrillOrbitRealData.cur_depth) + ",";
                str_SQL += string.Format("{0:f1}", myDrillOrbitRealData.inclination) + ",";
                str_SQL += string.Format("{0:f1}", myDrillOrbitRealData.azimuth) + ",";
                str_SQL += string.Format("{0:f1}", myDrillOrbitRealData.rotation) + ",";
                str_SQL += string.Format("{0:f1}", currXAxis) + ",";
                str_SQL += string.Format("{0:f1}", currYAxis) + ",";
                str_SQL += string.Format("{0:f1}", currZAxis) + ")";

                return sd_Analysis.executeSQL(str_SQL.ToString()).ToString();
            }
        }


        public static string CreateSQL_DrillHoleInfo(DrillAngleInfo it, string str_drill_index)
        {
            if (IsDataToText == "1")
            {
                return "";
            }
            else
            {
                string str_SQL = "";
                str_SQL = string.Format("exec  proc_DrillHoleInfo  '{0}','{1}','{2}','{3}','{4}','{5}','{6}' ",
                    str_drill_index, 0, BCDToString(it.StartTime), BCDToString(it.EndTime), 0, 0, 0);

                return sd_Analysis.executeSQL(str_SQL.ToString()).ToString();
            }
        }


        #endregion

        // 钻孔测深是否使用
        public static int isDrillDepthUsable(ref int num)
        {
            int ret;
            byte[] buff = new byte[512];
            int n;

            ret = SDUtils.read_sectors(500, 2, 0, ref buff);
            if (ret != 0)
            {
                if (buff[0] == 0X5A && buff[1] == 0X5A)
                {
                    n = buff[2] & 0xFF;
                    n |= ((buff[3] << 8) & 0xFF00);
                    num = n;
                    return 1;
                }
            }

            return 0;
        }

        // 钻孔角度是否使用
        public static int isDrillAngleUsable(ref int num)
        {
            int ret;
            byte[] buff = new byte[512];
            int n;

            ret = SDUtils.read_sectors(2000000, 2, 0, ref buff);
            if (ret != 0)
            {
                if (buff[0] == 0X5A && buff[1] == 0X5A)
                {
                    n = buff[2] & 0xFF;
                    n |= ((buff[3] << 8) & 0xFF00);
                    num = n;
                    return 1;
                }
            }

            return 0;
        }

        //把每个钻孔的钻孔轨二级目录。
        //把每个钻孔的钻孔轨迹都保存起来。
        public static int readDrillOrbitInfo(ref List<DrillOrbitInfo> myDrillOrbitInfoList, int n)
        {
            if (n == -1)
                return 0;

            try
            {
                int num = n;
                byte[] buffer = new byte[512];
                String2UIntValue myValue = new String2UIntValue();
                DrillOrbitInfo myDrillOrbitInfo = new DrillOrbitInfo();
                int start_sector = 3000010; //起始扇区是3000010
                int orbit_data_num = 0;
                byte[] pBuffer;

                while (num > 0)
                {
                    byte temp_number = 0;
                    SDUtils.read_sectors(start_sector, 1, 0, ref buffer); // SDUtils.read_sectors( start_sector, 2, 0, ref buffer);
                    start_sector++;
                    pBuffer = buffer;

                    while (temp_number < 8)
                    {
                        temp_number++;
                        num--;

                        myDrillOrbitInfo = new DrillOrbitInfo();

                        // 状态
                        //memcpy(myDrillOrbitInfo.status, pBuffer, 1);
                        myDrillOrbitInfo.status = pBuffer[0];

                        if (myDrillOrbitInfo.status != 0x5A)
                        {
                            pBuffer = BlockCopyOffSet(pBuffer, 64);
                            continue;
                        }

                        // 钻孔编号之前是3个字节的预留
                        myDrillOrbitInfo.drillNum.workPlace = (int) BCDtofloat(pBuffer, 4, 3, 0);
                        myDrillOrbitInfo.drillNum.field = (int) BCDtofloat(pBuffer, 7, 3, 0);
                        myDrillOrbitInfo.drillNum.drill = (int) BCDtofloat(pBuffer, 10, 2, 0);

                        // 存储数据开始扇区
                        memcpy(ref myValue.ac_value, pBuffer, 24, 4);
                        myDrillOrbitInfo.dataStartSector = myValue.ui_value;

                        // 存储数据结束扇区
                        memcpy(ref myValue.ac_value, pBuffer, 28, 4);
                        myDrillOrbitInfo.dataEndSector = myValue.ui_value;

                        // 存储数据组数
                        memcpy(ref myValue.ac_value, pBuffer, 32, 2);
                        myDrillOrbitInfo.savedGroupNums = myValue.ui_value;
                        orbit_data_num += myDrillOrbitInfo.savedGroupNums;

                        myDrillOrbitInfoList.Add(myDrillOrbitInfo);

                        pBuffer = BlockCopyOffSet(pBuffer, 64);
                    }
                }
            }
            catch (Exception ex)
            {
//                SystemConfig.WriteLog("readDrillOrbitInfo::" + ex.Message);
            }

            return 1;
        }

        //钻孔数据是否可用。如果可用就获得钻孔的数目、
        public static int getDrillHoleNum(int startSector, ref int number)
        {
            int ret;
            byte[] buff = new byte[512];
            int n;

            // ret = SDUtils.read_sectors(2000010, 1, 0, ref buff);
            ret = SDUtils.read_sectors(startSector, 1, 0, ref buff);

            if (ret != 0)
            {
                if (buff[0] == 0X5A && buff[1] == 0X5A)
                {
                    n = buff[2] & 0xFF;
                    n |= ((buff[3] << 8) & 0xFF00);
                    number = n + 1;
                    //需要向硬件组搞明白，既然范围是0-127，为什么还要用两个字节
                    //*number =*(unsigned short int)(buff+2);
                    return 1;
                }
            }
            return 0;
        }

        // 读取钻孔测深二级目录
        public static int readDrillDepthInfo(ref List<DrillDepthInfo> myDrillDepthInfoList, int n)
        {
            if (n == -1)
                return 0;

            int num = n;
            byte[] buffer = new byte[512];
            String2UIntValue myValue = new String2UIntValue();
            DrillDepthInfo myDrillDepthInfo = new DrillDepthInfo();
            int start_sector = 510; //起始扇区是510
            int total_depth_number = 0;
            byte[] pBuffer;

            while (num > 0)
            {
                try
                {
                    //每次读取一个扇区 SDUtils.read_sectors(start_sector, 2, 0, ref buffer);
                    SDUtils.read_sectors(start_sector, 1, 0, ref buffer);
                    start_sector++;
                    pBuffer = buffer;
                    byte temp_number = 0;

                    while (temp_number < 8)
                    {
                        temp_number++;
                        num--;
                        myDrillDepthInfo = new DrillDepthInfo();

                        // 状态
                        myDrillDepthInfo.status = pBuffer[0];
                        if (myDrillDepthInfo.status == 0xA5)
                        {
                            //无效的钻孔
                            pBuffer = BlockCopyOffSet(pBuffer, 64);
                            continue;
                        }

                        // 钻孔编号
                        myDrillDepthInfo.drillNum.workPlace = (int) BCDtofloat(pBuffer, 1, 3, 0);
                        myDrillDepthInfo.drillNum.field = (int) BCDtofloat(pBuffer, 4, 3, 0);
                        myDrillDepthInfo.drillNum.drill = (int) BCDtofloat(pBuffer, 7, 2, 0);

                        // 班组编号
                        myDrillDepthInfo.groupNum = (int) BCDtofloat(pBuffer, 9, 3, 0);

                        // 存储数据开始扇区
                        memcpy(ref myValue.ac_value, pBuffer, 28, 4);
                        myDrillDepthInfo.dataStartSector = myValue.ui_value;

                        // 存储数据结束扇区
                        memcpy(ref myValue.ac_value, pBuffer, 32, 4);
                        myDrillDepthInfo.dataEndSector = myValue.ui_value;

                        // 存储数据组数
                        memcpy(ref myValue.ac_value, pBuffer, 36, 4);

                        myDrillDepthInfo.savedGroupNums = myValue.ui_value;
                        total_depth_number += myDrillDepthInfo.savedGroupNums;

                        myDrillDepthInfoList.Add(myDrillDepthInfo);

                        //pBuffer += 64;
                        pBuffer = BlockCopyOffSet(pBuffer, 64);
                    }


                }
                catch (Exception ex)
                {
//                    SystemConfig.WriteLog("readDrillDepthInfo::" + ex.Message);
                }
            }
            return total_depth_number;
        }

        private static byte[] BlockCopyOffSet(byte[] pBuffer, int offset)
        {
            byte[] pBuffer_temp = new byte[pBuffer.Length - offset];
            Buffer.BlockCopy(pBuffer, 64, pBuffer_temp, 0, pBuffer.Length - offset);
            return pBuffer_temp;
        }

        // 读取钻孔角度二级目录. n是钻孔数目
        // 读取钻孔角度二级目录
        public static unsafe int readDrillAngleInfo(ref List<DrillAngleInfo> myDrillAngleInfoList, int n)
        {
            if (n == -1)
                return 0;

            int num = n;
            byte[] buffer = new byte[512];
            String2UIntValue myValue = new String2UIntValue();
            DrillAngleInfo myDrillAngleInfo = new DrillAngleInfo();
            int start_sector = 2000010; //起始扇区是2000010
            int total_angledata_num = 0;
            //C++ TO C# CONVERTER TODO TASK: Pointer arithmetic is detected on this variable, so pointers on this variable are left unchanged.
            byte[] pBuffer;

            while (num > 0)
            {
                byte temp_number = 0;
                SDUtils.read_sectors(start_sector, 1, 0, ref buffer); //( start_sector, 2, 0, ref buffer);
                start_sector++;
                pBuffer = buffer;

                while (temp_number < 8)
                {
                    temp_number++;
                    num--;

                    //memset(myDrillAngleInfo, 0, sizeof(DrillAngleInfo));
                    myDrillAngleInfo = new DrillAngleInfo();

                    // 状态
                    myDrillAngleInfo.status = pBuffer[0];

                    if (myDrillAngleInfo.status != 0xA5 && myDrillAngleInfo.status != 0x5A)
                    {
                        pBuffer = BlockCopyOffSet(pBuffer, 64);
                        continue;
                    }

                    // 钻孔编号编号之前是3个字节的预留
                    myDrillAngleInfo.drillNum.workPlace = (int) BCDtofloat(pBuffer, 4, 3, 0);
                    myDrillAngleInfo.drillNum.field = (int) BCDtofloat(pBuffer, 7, 3, 0);
                    myDrillAngleInfo.drillNum.drill = (int) BCDtofloat(pBuffer, 10, 2, 0);


                    //// 开始时间
                    //memcpy(ref myValue.ac_value, pBuffer, 12, 6);
                    //myDrillAngleInfo.StartTime = myValue.ui_value;

                    // 时间 6字节
                    for (int i = 0; i <= 5; i++)
                    {
                        myDrillAngleInfo.StartTime[i] = pBuffer[12 + i];
                        myDrillAngleInfo.EndTime[i] = pBuffer[18 + i];
                    }

                    // 存储数据开始扇区
                    memcpy(ref myValue.ac_value, pBuffer, 24, 4);
                    myDrillAngleInfo.dataStartSector = myValue.ui_value;

                    // 存储数据结束扇区
                    memcpy(ref myValue.ac_value, pBuffer, 28, 4);
                    myDrillAngleInfo.dataEndSector = myValue.ui_value;

                    // 存储数据组数
                    memcpy(ref myValue.ac_value, pBuffer, 32, 4);
                    myDrillAngleInfo.savedGroupNums = myValue.ui_value;
                    total_angledata_num += myDrillAngleInfo.savedGroupNums;

                    myDrillAngleInfoList.Add(myDrillAngleInfo);

                    pBuffer = BlockCopyOffSet(pBuffer, 64);
                    //注：一条钻孔角度及轨迹二级目录数据长度64字节，现使用33字节
                }
            }
            return 1;
        }

        // 组合钻孔测深二级目录和钻孔角度二级目录
        public static void composeDirectorys(ref List<DrillData> myDrillDataList)
        {
            for (int i = 0; i < drillAngleInfoList.Count; i++)
            {
                DrillDepthInfo it = new DrillDepthInfo();
                if (drillDepthInfoList.Count > i) it = drillDepthInfoList[i];
                DrillAngleInfo it2 = drillAngleInfoList[i];

                DrillData myDrillData = new DrillData();

                //if ((it.drillNum.drill == it2.drillNum.drill) && (it.drillNum.workPlace == it2.drillNum.workPlace) && (it.drillNum.field == it2.drillNum.field))
                {
                    DrillNumInfo t = new DrillNumInfo();

                    t.drill = it.drillNum.drill;
                    t.field = it.drillNum.field;
                    t.workPlace = it.drillNum.workPlace;

                    myDrillData.drillNum = t;
                    myDrillData.depthStatus = it.status;
                    myDrillData.angleStatus = it2.status;
                    myDrillData.depthSavedGroupNums = it.savedGroupNums;
                    myDrillData.angleSavedGroupNums = it2.savedGroupNums;
                    myDrillData.depthStartSector = it.dataStartSector;
                    myDrillData.depthEndSector = it.dataEndSector;
                    myDrillData.angleStartSector = it2.dataStartSector;
                    myDrillData.angleEndSector = it2.dataEndSector;

                    myDrillData.angleStartTime = it2.StartTime;
                    myDrillData.angleEndTime = it2.EndTime;

                    myDrillDataList.Add(myDrillData);
                    break;
                }
                //else
                //{
                //}
            }
        }

        #region buffer To Nodel

        // 从buffer中获取一个钻孔测深实际存储数据
        public static DrillDepthRealData getOneDepthData(byte[] buffer)
        {
            DrillDepthRealData myDrillDepthRealData = new DrillDepthRealData();

            // 钻孔编号 8字节.保持原有格式，使之做为字符串与DAS相对应
            myDrillDepthRealData.drillNum.workPlace = (int) BCDtofloat(buffer, 0, 3, 0);
            myDrillDepthRealData.drillNum.field = (int) BCDtofloat(buffer, 3, 3, 0);
            myDrillDepthRealData.drillNum.drill = (int) BCDtofloat(buffer, 6, 2, 0);

            // 班组编号 3字节
            myDrillDepthRealData.groupNum = (uint) BCDtofloat(buffer, 8, 3, 0);

            // 时间 6字节
            for (int i = 0; i <= 5; i++)
            {
                myDrillDepthRealData.time[i] = buffer[11 + i];
            }

            // 正转压力
            myDrillDepthRealData.forewardPressure = BCDtofloat(buffer, 17, 2, 1);

            // 反转压力
            myDrillDepthRealData.reversalPressure = BCDtofloat(buffer, 19, 2, 1);

            // 推进压力
            myDrillDepthRealData.ForwardPressure = BCDtofloat(buffer, 21, 2, 1);

            // 起拔压力
            myDrillDepthRealData.backPressure = BCDtofloat(buffer, 23, 2, 1);

            // 夹持器压力
            myDrillDepthRealData.holderPressure = BCDtofloat(buffer, 25, 2, 1);

            // 卡盘压力
            myDrillDepthRealData.chuckPressure = BCDtofloat(buffer, 27, 2, 1);

            // 位移传感器测量值
            var fu1 = buffer[29] / 10;


            byte[] bu1 = { (byte)(buffer[29] & 0x01), buffer[30], buffer[31] };
            myDrillDepthRealData.sensorData = BCDtofloat(bu1, 0, 3, 1) * (fu1 == 1 ? -1 : 1);

            // 当前深度
            var fu2 = buffer[32]/10;


            byte[] bu2 = {(byte) (buffer[32] & 0x01), buffer[33], buffer[34] };
            myDrillDepthRealData.currDepth = BCDtofloat(bu2, 0, 3, 1) * (fu2==1?-1:1);

            return myDrillDepthRealData;
        }

        // 从buffer中获取一个钻孔角度实际存储数据
        public static unsafe DrillAngleRealData getOneAngleData(byte[] buffer)
        {
            DrillAngleRealData myDrillAngleRealData = new DrillAngleRealData();
            String2FloatValue myValue = new String2FloatValue();

            // 时间 6字节
            for (int i = 0; i <= 5; i++)
            {
                myDrillAngleRealData.time[i] = buffer[2 + i];
            }

            // 俯仰角度 -90~90°
            memcpy(ref myValue.ac_value, buffer, 8, 4);
            //float A = BCDtofloat(buffer, 8, 1, 0);
            myDrillAngleRealData.inclination = BCDtofloat(buffer, 8, 3, 2, 1);

            // 翻滚角度 -180~180°
            memcpy(ref myValue.ac_value, buffer, 11, 3);
            myDrillAngleRealData.rotation = BCDtofloat(buffer, 11, 3, 2, 1); //BCDtofloat(buffer, 14, 3, 2);

            // 方位角度
            memcpy(ref myValue.ac_value, buffer, 14, 3);
            myDrillAngleRealData.azimuth = BCDtofloat(buffer, 14, 3, 2);

            //深度
            memcpy(ref myValue.ac_value, buffer, 29, 3);
            var fu1 = buffer[29] / 10;


            byte[] bu2 = { (byte)(buffer[29] & 0x01), buffer[30], buffer[31] };
            myDrillAngleRealData.currDepth = BCDtofloat(bu2, 0, 3, 1) * (fu1 == 1 ? -1 : 1);

           
            //myDrillAngleRealData.currDepth = BCDtofloat(buffer, 29, 3, 2);

            return myDrillAngleRealData;
        }

        #endregion

        // BCD转换成float
        public static unsafe float BCDtofloat(byte[] bcd, int start, int length, int precision, int FuShu = 0)
        {
            int Fu = 1; //负数

            int i;
            int tmp;
            float dec = 0.0F;
            for (i = 0; i < length; i++)
            {

                if (i == 0 && FuShu == 1 && ((bcd[start + i] >> 4) & 0x0F) == 1)
                {
                    tmp = (bcd[start + i] & 0x0F);
                    Fu = -1;
                }
                else
                    tmp = ((bcd[start + i] >> 4) & 0x0F)*10 + (bcd[start + i] & 0x0F);

                dec += tmp*((float) Math.Pow((float) 100, (float) length - 1 - i));
            }

            float result = (float) dec;
            for (i = 0; i != precision; i++)
            {
                result = result/(float) 10;
            }
            return (float) Math.Round(result*Fu, precision);
        }


        public static int check_drill_info(DrillAngleInfo it, string str_drill_index)
        {
            if (IsDataToText == "1")
            {
                //SystemConfig.DeleteLine(ID);
            }
            else
            {
                string my_SQL = string.Format("exec [proc_DrillHoleInfo] '{0}','{1}','{2}','{3}','{4}','{5}','{6}' ;",
                    str_drill_index, 0, sd_Analysis.BCDToString(it.StartTime), sd_Analysis.BCDToString(it.EndTime), 0, 0, 0);
                my_SQL += string.Format("exec proc_Insert_Original '{0}' ;", str_drill_index);
                executeSQL(my_SQL.ToString());
            }
            return 1;
        }

        //检查当前数据库表是否存在，如果不存在就创建一个
        public static int check_table_exist(string str_tableName, string ID = "")
        {
            if (IsDataToText == "1")
            {
                SystemConfig.DeleteLine(ID);
            }
            else
            {
                string my_SQL = "exec Proc_CreateDrillHoleRun " + str_tableName.Substring(str_tableName.Length - 6);
                executeSQL(my_SQL.ToString());
            }
            return 1;
        }

        public static DrillOrbitRealData getOneOrbitData(byte[] buffer)
        {
            DrillOrbitRealData myDrillOrbitRealData = new DrillOrbitRealData();
            String2FloatValue myValue = new String2FloatValue();

            // 钻孔编号 8字节，前面是2个自己的预留
            myDrillOrbitRealData.drillNum.workPlace = (int) BCDtofloat(buffer, 2, 3, 0);
            myDrillOrbitRealData.drillNum.field = (int) BCDtofloat(buffer, 5, 3, 0);
            myDrillOrbitRealData.drillNum.drill = (int) BCDtofloat(buffer, 8, 2, 0);

            // 时间 6字节
            for (int i = 0; i <= 5; i++)
            {
                myDrillOrbitRealData.time[i] = buffer[10 + i];
            }

            // 当前深度
            memcpy(ref myValue.ac_value, buffer, 16, 4);
            myDrillOrbitRealData.cur_depth = myValue.f_value;

            // 俯仰角度
            memcpy(ref myValue.ac_value, buffer, 20, 4);
            myDrillOrbitRealData.inclination = myValue.f_value;

            // 方位角度
            memcpy(ref myValue.ac_value, buffer, 24, 4);
            myDrillOrbitRealData.azimuth = myValue.f_value;

            // 翻滚角度
            memcpy(ref myValue.ac_value, buffer, 28, 4);
            myDrillOrbitRealData.rotation = myValue.f_value;

            return myDrillOrbitRealData;
        }

        private static void memcpy(ref byte[] ac_value, byte[] buffer, int start, int len)
        {
            ac_value = new byte[len];
            Buffer.BlockCopy(buffer, start, ac_value, 0, len);
        }

        
    }

    public class String2FloatValue
    {
        public byte[] ac_value;

        public float f_value
        {
            get
            {
                if (ac_value.Length == 4)
                    return Convert.ToSingle(BitConverter.ToSingle(ac_value, 0).ToString());
                else
                    return 0;
            }
        }
    }

    public class String2UIntValue
    {
        public byte[] ac_value;

        public int ui_value
        {
            get
            {
                if (ac_value.Length == 4)
                    return (int) (ac_value[0] | ac_value[1] << 8 | ac_value[2] << 16 | ac_value[3] << 24);
                else if (ac_value.Length == 2)
                    return (int) (ac_value[0] | ac_value[1] << 8);
                else
                    return 0;
            }
        }
    }


    // 钻孔编号结构体 8字节
    public class DrillNumInfo
    {
        public int workPlace; // 工作面 -> (24bit)
        public int field; // 钻场 -> (24bit)
        public int drill; // 钻孔 -> (16bit)
    }

    // 钻孔测深二级目录结构体 -> 固定64字节, 现使用40字节
    public class DrillDepthInfo
    {
        public byte status; // 状态 -> (1字节)
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)
        public int groupNum; // 班组编号 -> (3字节)

        public byte[] StartTime = new byte[6]; //钻孔开始时间：年、月、日、时、分、秒，用16进制表示-> (6字节)
        public byte[] EndTime = new byte[6]; // 孔结束时间：年、月、日、时、分、秒。用16进制表示 -> (6字节)

        public int dataStartSector; // 钻孔测深存储数据开始扇区 -> (4字节)
        public int dataEndSector; // 钻孔测深存储数据结束扇区 -> (4字节)
        public int savedGroupNums; // 本钻孔存储数据组数 -> (4字节)
    }

    // 钻孔测深存储数据 -> 固定使用64字节, 现使用35字节
    public class DrillDepthRealData
    {
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)
        public uint groupNum; // 班组编号 -> (3字节)
        public byte[] time = new byte[6]; // 时间 -> (6字节)
        public float forewardPressure; // 正转压力 -> (2字节)
        public float reversalPressure; // 反转压力 -> (2字节)
        public float ForwardPressure; // 前（推）进压力 -> (2字节)
        public float backPressure; // 后退（起拔）压力 -> (2字节)
        public float holderPressure; // 夹持器压力 -> (2字节)
        public float chuckPressure; // 卡盘压力 -> (2字节)
        public float sensorData; // 位移传感器测量值 -> (3字节)
        public float currDepth; // 当前深度 -> (3字节)

        public string TableName { get; set; }
        public string DrillIndex { get; set; }


        public override string ToString()
        {
            return string.Format("{0}^{1}^{2}^{3}^{4}^{5}^{6}"
                , DrillIndex, sd_Analysis.BCDToString(time), currDepth, groupNum, holderPressure, chuckPressure, sensorData);
        }
    }

    // 钻孔角度二级目录结构体 -> 固定使用64字节, 现使用33字节
    public class DrillAngleInfo
    {
        public byte status; // 状态 -> (1字节)
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)

        public byte[] StartTime = new byte[6]; //钻孔开始时间：年、月、日、时、分、秒，用16进制表示-> (6字节)
        public byte[] EndTime = new byte[6]; // 孔结束时间：年、月、日、时、分、秒。用16进制表示 -> (6字节)

        public int dataStartSector; // 钻孔角度存储数据开始扇区 -> (4字节)
        public int dataEndSector; // 钻孔角度存储数据结束扇区 -> (4字节)
        public int savedGroupNums; // 本钻孔存储数据组数 -> (4字节)
    }

    // 钻孔角度存储数据 -> 固定使用32字节, 现使用26字节
    public class DrillAngleRealData
    {
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)
        public byte[] time = new byte[6]; // 时间 -> (6字节)
        public float inclination; // 俯仰角度 -> (4字节)
        public float azimuth; // 方位角度 -> (4字节)
        public float rotation; // 翻滚角度 -> (4字节)

        public float currDepth; // 当前深度 -> (3字节)

        public string TableName { get; set; }
        public string DrillIndex { get; set; }
        public float XAxis { get; set; }
        public float YAxis { get; set; }
        public float ZAxis { get; set; }

        public override string ToString()
        {
            return string.Format("{0}^{1}^{2}^{3}^{4}^{5}^{6}^{7}^{8}"
                , DrillIndex, sd_Analysis.BCDToString(time), currDepth, inclination, azimuth, rotation, XAxis, YAxis, ZAxis);
        }
    }


    // 钻孔轨迹二级目录
    public class DrillOrbitInfo
    {
        public byte status; // 状态 -> (1字节)
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)
        public int dataStartSector; // 钻孔角度存储数据开始扇区 -> (4字节)
        public int dataEndSector; // 钻孔角度存储数据结束扇区 -> (4字节)
        public int savedGroupNums; // 本钻孔存储数据组数 -> (4字节)
    }

    // 钻孔轨迹存储数据
    public class DrillOrbitRealData
    {
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)
        public byte[] time = new byte[6];
        public float cur_depth;
        public float inclination;
        public float azimuth;
        public float rotation;
        public string TableName { get; set; }
        public string DrillIndex { get; set; }
        public float XAxis { get; set; }
        public float YAxis { get; set; }
        public float ZAxis { get; set; }
    }


    // 钻孔深度和角度组合后的数据结构
    public class DrillData
    {
        public byte depthStatus;
        public byte angleStatus;
        public DrillNumInfo drillNum = new DrillNumInfo(); // 钻孔编号 -> (8字节)
        public int depthSavedGroupNums; // 本钻孔测深数据组数
        public int angleSavedGroupNums; // 本钻孔角度数据组数
        public int depthStartSector; // 钻孔测深存储数据开始扇区 -> (4字节)
        public int depthEndSector; // 钻孔测深存储数据结束扇区 -> (4字节)
        public int angleStartSector; // 钻孔角度存储数据开始扇区 -> (4字节)
        public int angleEndSector; // 钻孔角度存储数据结束扇区 -> (4字节)

        public byte[] angleStartTime = new byte[6]; // 钻孔开始时间 -> (6字节)
        public byte[] angleEndTime = new byte[6]; // 钻孔结束时间 -> (6字节)

    }
}